package br.com.sis.rh.dao;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.sis.rh.entity.Alocacao;
import br.com.sis.rh.entity.Candidato;
import br.com.sis.rh.entity.Cargo;
import br.com.sis.rh.entity.CargoPretendido;
import br.com.sis.rh.entity.CursoExtra;
import br.com.sis.rh.entity.CursoGraduacao;
import br.com.sis.rh.entity.Empresa;
import br.com.sis.rh.entity.Entidade;
import br.com.sis.rh.entity.GraduacaoProfissional;
import br.com.sis.rh.entity.Idioma;
import br.com.sis.rh.entity.IdiomaDominado;
import br.com.sis.rh.entity.InstituicaoEnsino;
import br.com.sis.rh.entity.ModalidadeContratacao;
import br.com.sis.rh.entity.Pos;
import br.com.sis.rh.entity.PosGraduacaoProfissional;
import br.com.sis.rh.entity.TipoCursoPos;

@Repository
public class CandidatoDAOImpl extends GenericDAOImpl<Candidato> implements CandidatoDAO {
	
	public CandidatoDAOImpl() {
		super(Candidato.class);
	}

	@Autowired
	private SessionFactory sessionFactory;
	
	@Autowired
	private SessionFactory sessionFactoryAux;
	
	@Override
	public void incluirEndereco(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		candidatoAlterado.getDadosPessoais().setEndereco(objeto.getDadosPessoais().getEndereco());
	}

	@Override
	public void incluirAreasAtuacao(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		candidatoAlterado.setAreaAtuacao(objeto.getAreaAtuacao());
	}
	
	@Override
	public void incluirSegmentos(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		candidatoAlterado.setSegmento(objeto.getSegmento());
	}
	
	@Override
	public void incluirCompetencias(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		candidatoAlterado.setCompetencia(objeto.getCompetencia());
	}
	
	@Override
	public void incluirAlocacao(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(Alocacao aloc : objeto.getAlocacao()) {
			candidatoAlterado.getAlocacao().add(aloc);	
		}
	}
	
	@Override
	public void incluirGraduacaoProfissional(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(GraduacaoProfissional grad : objeto.getGraduacaoProfissional()) {
			candidatoAlterado.getGraduacaoProfissional().add(grad);	
		}
	}

	@Override
	public void incluirPosGraduacao(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(PosGraduacaoProfissional pos : objeto.getPosGraduacaoProfissional()) {
			candidatoAlterado.getPosGraduacaoProfissional().add(pos);	
		}
	}

	@Override
	public void incluirCursoExtra(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(CursoExtra cx : objeto.getCursoExtra()) {
			candidatoAlterado.getCursoExtra().add(cx);	
		}
	}
	
	@Override
	public void incluirCargoPretendido(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(CargoPretendido cp : objeto.getCargoPretendido()) {
			candidatoAlterado.getCargoPretendido().add(cp);	
		}
	}
	
	@Override
	public void incluirIdiomaDominado(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		for(IdiomaDominado id : objeto.getIdiomaDominado()) {
			candidatoAlterado.getIdiomaDominado().add(id);	
		}
	}
	
	@Override
	public void incluirPretensaoSalarial(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		candidatoAlterado.setPretensaoSalarial(objeto.getPretensaoSalarial());
	}	
	
	@Override
	public void incluirRemuneracao(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		candidatoAlterado.setRemuneracao(objeto.getRemuneracao());
	}
	
	@Override
	public void incluirAvaliacao(Candidato objeto) {
		Candidato candidatoAlterado = recuperarObjetoPorID(objeto);
		
		candidatoAlterado.setAvaliacao(objeto.getAvaliacao());
	}	
	
	@Override
	@Transactional
	public Candidato listarPorObjeto(Entidade objeto, String joinTable) {		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(objeto.getClass());

		criteria.add(Restrictions.eq("id",  objeto.getId()));
		
		criteria.setFetchMode(joinTable, FetchMode.JOIN);
		
		criteria.createCriteria(joinTable);
		
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		
		Candidato candidatoRetornado = (Candidato) criteria.uniqueResult();
		
		if(candidatoRetornado != null) {
			
			if("graduacaoProfissional".equals(joinTable)) {
				complementaListaGraduacao(candidatoRetornado);
			} else if("posGraduacaoProfissional".equals(joinTable)) {
				complementaListaPosGraduacao(candidatoRetornado);
			} else if("alocacao".equals(joinTable)) {
				complementaListaAlocacao(candidatoRetornado);
			} else if("cursoExtra".equals(joinTable)) {
				complementaListaCursoExtra(candidatoRetornado);
			} else if("cargoPretendido".equals(joinTable)) {
				complementaListaCargoPretendido(candidatoRetornado);
			} else if("idiomaDominado".equals(joinTable)) {
				complementaIdiomaDominado(candidatoRetornado);
			}
			
			return (Candidato) candidatoRetornado;
			
		} else {
			return null;			
		}
	}
	
	@Override
	@Transactional(value="transactionManagerAux")
	public Candidato recuperarCandidatoAux(Integer id) {
		return (Candidato) sessionFactoryAux.getCurrentSession().get(Candidato.class, id);
	}
	
	private void complementaListaGraduacao(Candidato candidatoRetornado) {
		for(GraduacaoProfissional graduacao : candidatoRetornado.getGraduacaoProfissional()) {
			
			CursoGraduacao curso = (CursoGraduacao)sessionFactory.getCurrentSession().get(CursoGraduacao.class, graduacao.getCursoGraduacao().getId());
			
			InstituicaoEnsino instituicao = (InstituicaoEnsino)sessionFactory.getCurrentSession().get(InstituicaoEnsino.class, graduacao.getInstituicaoEnsino().getId());
			
			graduacao.setCursoGraduacao(curso);
			graduacao.setInstituicaoEnsino(instituicao);
		}
	}
	
	private void complementaListaPosGraduacao(Candidato candidatoRetornado) {
		for(PosGraduacaoProfissional posGraduacao : candidatoRetornado.getPosGraduacaoProfissional()) {
			
			TipoCursoPos tipoCursoPos = (TipoCursoPos)sessionFactory.getCurrentSession().get(TipoCursoPos.class, posGraduacao.getTipoCursoPos().getId());
			
			Pos pos = (Pos)sessionFactory.getCurrentSession().get(Pos.class, posGraduacao.getPos().getId());
			
			InstituicaoEnsino instituicao = (InstituicaoEnsino)sessionFactory.getCurrentSession().get(InstituicaoEnsino.class, posGraduacao.getInstituicaoEnsino().getId());
			
			posGraduacao.setTipoCursoPos(tipoCursoPos);
			posGraduacao.setPos(pos);
			posGraduacao.setInstituicaoEnsino(instituicao);
		}
	}

	private void complementaListaCursoExtra(Candidato candidatoRetornado) {
		for(CursoExtra cursoExtra : candidatoRetornado.getCursoExtra()) {
			
			InstituicaoEnsino instituicao = (InstituicaoEnsino)sessionFactory.getCurrentSession().get(InstituicaoEnsino.class, cursoExtra.getInstituicaoEnsino().getId());
			
			cursoExtra.setInstituicaoEnsino(instituicao);
		}
	}

	private void complementaListaAlocacao(Candidato candidatoRetornado) {
		for(Alocacao alocacao : candidatoRetornado.getAlocacao()) {
			
			Cargo cargo = (Cargo) sessionFactory.getCurrentSession().get(Cargo.class, alocacao.getCargo().getId());
			
			Empresa empresa = (Empresa)sessionFactory.getCurrentSession().get(Empresa.class, alocacao.getEmpresa().getId());
			
			ModalidadeContratacao modalidadeContratacao = (ModalidadeContratacao)sessionFactory.getCurrentSession().get(ModalidadeContratacao.class, alocacao.getModalidadeContratacao().getId());
			
			alocacao.setCargo(cargo);
			alocacao.setEmpresa(empresa);
			alocacao.setModalidadeContratacao(modalidadeContratacao);
		}
	}
	
	private void complementaListaCargoPretendido(Candidato candidatoRetornado) {
		for(CargoPretendido cargoPretendido : candidatoRetornado.getCargoPretendido()) {
			
			Cargo cargo = (Cargo)sessionFactory.getCurrentSession().get(Cargo.class, cargoPretendido.getCargo().getId());
			
			cargoPretendido.setCargo(cargo);
		}
	}
	
	private void complementaIdiomaDominado(Candidato candidatoRetornado) {
		for(IdiomaDominado idiomaDominado : candidatoRetornado.getIdiomaDominado()) {
			
			Idioma idioma = (Idioma)sessionFactory.getCurrentSession().get(Idioma.class, idiomaDominado.getIdioma().getId());
			
			idiomaDominado.setIdioma(idioma);
		}
	}

}
